/**********************************************************************************************************************
 *
 * Project:    mGameEngine
 * File:       bmploader.cpp
 * Author:     karooolek
 * Created on: 2009-03-22
 *
 **********************************************************************************************************************/

#include "bmploader.h"

namespace mGameEngine
{
namespace Graphics
{

BMPLoader::BMPLoader(): ImageLoader()
{
}

BMPLoader::BMPLoader(const String &filename) : ImageLoader(filename)
{
}

BMPLoader::~BMPLoader()
{
}

void BMPLoader::load()
{
    // based on BMPLoader by Chris Backhouse
    // cjbackhouse@hotmail.com
    // www.backhouse.tk

    // begin image loading
    _state = 0.0f;

    // open file for reading in binary mode
    FILE *file = fopen(_filename.c_str(), "rb");
    if(!file)
    {
        return;
    }

    // read the 54 byte main header
    uint8 header[54];
    fread(header, 54, 1, file);

    // all bitmaps should start "BM"
    if(header[0] != 'B' || header[1] != 'M')
    {
        fclose(file);
        return;
    }

    // read data from header
    uint offset = *reinterpret_cast<uint *>(header + 10);
    uint width = *reinterpret_cast<uint *>(header + 18);
    uint height = *reinterpret_cast<uint *>(header + 22);
    uint8 bpp = header[28];
    uint8 *data = NULL;

    // read data to buffer
    uint8 colors[256 * 4];

    // 32bit RGBA
    if(bpp == 32)
    {
        data = new uint8[width * height * 4];
        fread(data, width * height * 4, 1, file);

        // swizzle BGRA to RGBA
        for(uint x = 0; x < width * height * 4; x += 4)
        {
            uint8 temp = data[x];
            data[x] = data[x + 2];
            data[x + 2] = temp;
        }
    }

    // 24bit RGB
    else if(bpp == 24)
    {
        fseek(file, offset, SEEK_SET);

        data = new uint8[width * height * 3];
        fread(data, width * height * 3, 1, file);

        // swizzle BGR -> RGB
        for(uint x = 0; x < width * height * 3; x += 3)
        {
            uint8 temp = data[x];
            data[x] = data[x + 2];
            data[x + 2] = temp;
        }
    }

    // 8bit
    else if(bpp == 8)
    {
        fread(colors, 256 * 4, 1, file);
        fseek(file, offset, SEEK_SET);

        data = new uint8[width * height];
        fread(data, width * height, 1, file);
    }

    // invalid image
    else
    {
        fclose(file);
        delete[] data;
        return;
    }

    // delete old image
    if(_image)
    {
        delete _image;
    }

    // create new image
    _image = new Image(data, width, height, bpp);

    // close file
    fclose(file);
    delete[] data;

    // image loaded!
    _state = 1.0f;
}

}
}

